/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2013-2014 jfinal app. jfapp Group.
 */

package app.models.member;

import app.constant.MemberConstant;
import app.constant.OrderConstant;
import app.dtos.ProductBizDto;
import app.kit.CommonKit;
import app.kit.TypeKit;
import app.services.profit.ProfitService;
import com.google.common.base.Strings;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;
import goja.StringPool;
import goja.annotation.TableBind;
import goja.plugins.sqlinxml.SqlKit;
import goja.tuples.Pair;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.Days;

import java.math.BigDecimal;
import java.util.List;

import static app.Const.FIELD_AMOUNT;
import static app.Const.FIELD_COLLECTION_MODE;
import static app.Const.FIELD_MEMBER;
import static app.Const.FIELD_PRODUCT;
import static app.Const.FIELD_TIME_LIMIT_UNIT;
import static app.Const.FIELD_YIELD;
import static app.Const.YES;
import static app.constant.MemberConstant.DEFAULT_STATUS;
import static app.constant.MemberConstant.PLAYMONEY_NO;
import static app.constant.MemberConstant.PLAYMONEY_OK;
import static app.constant.MemberConstant.PRODUCT_EXPIRE;
import static app.constant.MemberConstant.PRODUCT_FOUND;
import static app.constant.MemberConstant.PRODUCT_SALE;
import static app.constant.MemberConstant.PRODUCT_SALES_SUCCESS;
import static app.constant.MemberConstant.PRODUCT_SALE_FAIL;
import static app.constant.MemberConstant.REDEEM_AUDIT;
import static app.constant.MemberConstant.REDEEM_SUCCESS;
import static app.constant.MemberConstant.TRANSFER_AUDIT;
import static app.constant.MemberConstant.TRANSFER_AUDIT_SUCCESS;
import static app.constant.MemberConstant.TRANSFER_TRADE_FAIL;
import static app.constant.MemberConstant.TRANSFER_TRADE_SUCCESS;

/**
 * <p>
 * The table rlm_product mapping model.
 * </p>
 */
@TableBind(tableName = "rlm_member_product")
public class MemberProduct extends Model<MemberProduct> {

    /**
     * The public dao.
     */
    public static final MemberProduct dao = new MemberProduct();

    private static final long serialVersionUID = -8175212043701236261L;


    public static final String FIELD_PRODUCT_STATUS   = "product_status";
    public static final String FIELD_TRANSFER_STATUS  = "transfer_status";
    public static final String FIELD_REDEEM_STATUS    = "redeem_status";
    public static final String FIELD_PLAYMONEY_STATUS = "playmoney_status";


    public List<MemberProduct> findByTypeWithPage(int memerId, int status, int page) {
        final Pair<Integer, Integer> pair = CommonKit.pageOffset(page);
        return find(SqlKit.sql("memberproduct.findByTypeWithPage"), memerId, status, pair.getValue1(), pair.getValue0());
    }

    public MemberProduct findProductById(int id) {
        return findFirst(SqlKit.sql("memberproduct.findProductById"), id);
    }

    public MemberProduct findProductInfoById(int id) {
        return findFirst(SqlKit.sql("memberproduct.findProductInfoById"), id);
    }

    public List<MemberProduct> findByMember(int memberId) {
        return find(SqlKit.sql("memberproduct.findByMember"), memberId);
    }

    /**
     * 查询所有会员的到期收益的产品列表，同时没有进行撤单和转让的产品列表。
     *
     *  查询产品状态为 到期，赎回状态为0，转让状态为0的会员产品
     *
     * @param page           页码
     * @param collectionMode 收益模式
     * @return 会员产品数据
     */
    public List<MemberProduct> findByMaturityYield(int page, int collectionMode) {
        final Pair<Integer, Integer> objects = CommonKit.pageOffset(page);
        String sql = SqlKit.sql("memberproduct.findByMaturityYield");
        return find(sql,
                PRODUCT_EXPIRE, TRANSFER_AUDIT_SUCCESS, DEFAULT_STATUS, REDEEM_AUDIT, PLAYMONEY_NO,
                collectionMode, objects.getValue1(), objects.getValue0());
    }

    public List<MemberProduct> findByProductProfit(int collectionMode, int product) {
//        final Pair<Integer, Integer> objects = CommonKit.pageOffset(page);
        String sql = SqlKit.sql("memberproduct.findByProductProfit");
        return find(sql,
                PRODUCT_EXPIRE, TRANSFER_AUDIT_SUCCESS, DEFAULT_STATUS, REDEEM_AUDIT, PLAYMONEY_NO,
                collectionMode, product/*, objects.getValue1(), objects.getValue0()*/);
    }

    /**
     * 根据id 关联查询 产品的相关信息
     * @param mem_pid
     * @return
     */
    public MemberProduct findRelationById(int mem_pid) {
        return findFirst(SqlKit.sql("memberproduct.findRelationById"), mem_pid);
    }

    /**
     * 通过会员产品id 查询 为转让产品表准备数据
     * @param mem_pid
     * @return
     */
    public MemberProduct findRelationToTrsById(int mem_pid) {
        return findFirst(SqlKit.sql("memberproduct.findRelationToTrsById"), mem_pid);
    }

    public List<MemberProduct> findByProductWithPage(int productId, int page, int pageSize) {
        final Pair<Integer, Integer> offsets = CommonKit.pageOffset(page, pageSize);
        return find(SqlKit.sql("memberproduct.findByProductWithPage"), productId, REDEEM_SUCCESS, offsets.getValue1(), offsets.getValue0());
    }

    /**
     * 取得某个产品的 所有会员购买纪录并没有申请退单的纪录
     *
     * @param productId 产品ID
     * @param page      页码
     * @param pageSize  每页数量
     * @return 每页产品
     */
    public List<MemberProduct> findByProductAndNoRedeem(int productId, int page, int pageSize) {
        final Pair<Integer, Integer> offsets = CommonKit.pageOffset(page, pageSize);
        return find(SqlKit.sql("memberproduct.findByProductAndNoRedeem"), productId, DEFAULT_STATUS, offsets.getValue1(), offsets.getValue0());
    }

    /**
     * @param memberId          会员ID
     * @param productId         产品ID
     * @param principal         投资本金
     * @param totalAmount       购买金额
     * @param resp_date         响应时间
     * @param collection_mode   收益模式
     * @param yield             收益率
     * @param transferProductId 转让产品ID
     * @return 会员产品
     */
    public static MemberProduct buildTransferProduct(int memberId, int productId,
                                                     BigDecimal principal, BigDecimal totalAmount,
                                                     DateTime resp_date,
                                                     int collection_mode, float yield, long transferProductId) {
        MemberProduct memberProduct = buildBuyProduct(memberId, productId, principal, resp_date, collection_mode, yield);
        memberProduct.set("transfer_product", transferProductId);
        // 购买价格
        memberProduct.set("transfer_price", totalAmount);
        return memberProduct;
    }

    /**
     * 构建会员产品
     *
     * @param memberId        会员ID
     * @param productId       产品ID
     * @param decimal_amount  价格
     * @param resp_date       购买时间
     * @param collection_mode 收益模式
     * @param yield           收益率
     * @return 会员产品
     */
    public static MemberProduct buildBuyProduct(int memberId, int productId,
                                                BigDecimal decimal_amount, DateTime resp_date,
                                                int collection_mode, float yield) {
        MemberProduct memberProduct = new MemberProduct();
        memberProduct.set(FIELD_MEMBER, memberId);
        memberProduct.set(FIELD_PRODUCT, productId);
        memberProduct.set(FIELD_AMOUNT, decimal_amount);
        memberProduct.set("buy_time", resp_date);
        memberProduct.set("buy_time_year", resp_date.getYear());
        memberProduct.set("buy_time_month", resp_date.getMonthOfYear());
        memberProduct.set("buy_time_day", resp_date.getDayOfMonth());
        memberProduct.set(FIELD_COLLECTION_MODE, collection_mode);
        // 会员产品中的期限信息
        memberProduct.set(FIELD_YIELD, yield);
        return memberProduct;
    }

    public MemberProduct findDetailById(int id, int member) {
        return findFirst(SqlKit.sql("memberproduct.findDetailById"), id, member);
    }

    /**
     * 检查会员产品状态，根据三个状态来进行判断
     * <p/>
     * 需要关联查询对应产品的赎回（退单）和转让限制
     *
     * @return value0 表示转让业务 value1 表示退单业务
     */
    public ProductBizDto bizStatus() {

        int productStatus = TypeKit.getInt(this, FIELD_PRODUCT_STATUS);
        int redeemStatus = TypeKit.getInt(this, FIELD_REDEEM_STATUS);
        int transferStatus = TypeKit.getInt(this, FIELD_TRANSFER_STATUS);
        int playmoneyStatus = TypeKit.getInt(this, FIELD_PLAYMONEY_STATUS);

        DateTime buyTime = TypeKit.getDateTime(this, "buy_time");
        int hold_days = 0;
        if (buyTime != null) {
            hold_days = Days.daysBetween(buyTime, DateTime.now()).getDays();
        }


        String transfer_flag = this.getStr("transfer_flag");
        String redeem_flag = this.getStr("redeem_flag");
        int transfer_holding_days = TypeKit.getInt(this, "transfer_holding_days");

        boolean transfer = false, cancel = false;
        String transferDesc = StringPool.EMPTY, cancelDesc = StringPool.EMPTY, playmoneyDesc = StringPool.EMPTY;
        if (StringUtils.equals(transfer_flag, YES)) {
            if (hold_days >= transfer_holding_days) {
                // 超过转让限制
                if ((productStatus == PRODUCT_FOUND)
                        && (transferStatus == DEFAULT_STATUS || transferStatus == TRANSFER_TRADE_FAIL)
                        && (redeemStatus == DEFAULT_STATUS)) {
                    transfer = true;
                } else {
                    switch (productStatus) {
                        case PRODUCT_SALE:
                        case PRODUCT_SALES_SUCCESS:
                            transferDesc = "产品认购中,无法转让";
                            break;
                        case PRODUCT_SALE_FAIL:
                            transferDesc = "产品认购失败,无法转让";
                            break;
                        case PRODUCT_EXPIRE:
                            transferDesc = "产品到期结束,无法转让";
                            if(playmoneyStatus == PLAYMONEY_OK){
                                playmoneyDesc = "收益已打款";
                            }
                            break;
                    }
                    switch (transferStatus) {
                        case TRANSFER_AUDIT:
                            transferDesc = "产品申请转让中";
                            break;
                        case TRANSFER_AUDIT_SUCCESS:
                            transferDesc = "产品挂单转让中";
                            break;
                        case TRANSFER_TRADE_SUCCESS:
                            transferDesc = "产品已转让";
                            if(playmoneyStatus == PLAYMONEY_OK){
                                playmoneyDesc = "转让已打款";
                            }
                            break;
                    }
                    if(redeemStatus > DEFAULT_STATUS){
                        switch (redeemStatus){
                            case REDEEM_AUDIT:
                                transferDesc = "退单申请中";
                                break;
                            case REDEEM_SUCCESS:
                                transferDesc = "已退单";
                                if(playmoneyStatus == PLAYMONEY_OK){
                                    playmoneyDesc = "已退单已打款";
                                } else{
                                    playmoneyDesc = "已退单未打款";
                                }
                                break;
                        }
                    }
                }
            } else {
                transferDesc = "持有"+transfer_holding_days + "天后才可以转让，目前持有" + hold_days + "天";
            }
        } else {
            transferDesc = "该产品不允许转让";
        }
        if (StringUtils.equals(redeem_flag, YES)) {
            // 允许退单
            if (productStatus == PRODUCT_SALE && redeemStatus == DEFAULT_STATUS) {
                cancel = true;
            } else {
                switch (productStatus) {
                    case PRODUCT_SALES_SUCCESS:
                        cancelDesc = "产品认购成功,无法退单";
                        break;
                    case PRODUCT_SALE_FAIL:
                        cancelDesc = "产品认购失败,无法退单";
                        break;
                    case PRODUCT_EXPIRE:
                        cancelDesc = "产品到期结束,无法退单";
                }
                switch (redeemStatus) {
                    case REDEEM_AUDIT:
                        cancelDesc = "退单申请中 ";
                        break;
                    case REDEEM_SUCCESS:
                        cancelDesc = "已退单 ";
                        if(playmoneyStatus == PLAYMONEY_OK){
                            playmoneyDesc = "已退单已打款";
                        } else{
                            playmoneyDesc = "已退单未打款";
                        }
                        break;
                }
            }
        }else {
            cancelDesc = "该产品不允许退单";
        }

         return ProductBizDto.create(cancel, transfer, transferDesc, cancelDesc, playmoneyDesc);
    }

    public BigDecimal profit() {
        // 计算预期收益
        int time_unit = TypeKit.getInt(this, "time_limit");
        String time_limit_unit = this.getStr(FIELD_TIME_LIMIT_UNIT);
        int hold_days = CommonKit.termDays(time_unit, time_limit_unit, TypeKit.getDateTime(this, "valuedate"));

        return ProfitService.me.onceProfit(this.getBigDecimal(FIELD_AMOUNT),
                this.getBigDecimal(FIELD_YIELD), TypeKit.getInt(this, "basic_days"), hold_days);

    }

    /**
     * 设置后的状态名称 字段名称为：playmoney_status_name
     * @return
     * @param records
     */
    public List<Record> setPlayStatusName(List<Record> records){
        for (Record record : records) {
            Number status = record.getNumber("playmoney_status");
            if(null!=status){
                int playmoney_status =  status.intValue();
                switch(playmoney_status){
                    case MemberConstant.PLAYMONEY_NO : record.set("playmoney_status_name","未打款");break;
                    case MemberConstant.PLAYMONEY_SUBMIT : record.set("playmoney_status_name","提交打款");break;
                    case MemberConstant.PLAYMONEY_OK : record.set("playmoney_status_name","打款成功");break;
                    default:record.set("playmoney_status_name","未知");break;
                }
            }
        }
        return records;
    }

    /**
     * 设置订单类型
     * @param records
     * @return
     */
    public List<Record> setOrderTypeName(List<Record> records){
        for (Record record : records) {
            String order_type = record.getStr("order_type");
            if(!Strings.isNullOrEmpty(order_type)){
                if(order_type.equals(OrderConstant.BUY_TYPE)){
                    record.set("order_type_name","投资(购买)");
                }else if(order_type.equals(OrderConstant.TFR_TYPE)){
                    record.set("order_type_name","投资(转让)");
                }
            }
        }
        return records;
    }

    public int findByProductCount(int productId) {
        MemberProduct memberProduct = findFirst(SqlKit.sql("memberproduct.findByProductCount"), productId, MemberConstant.DEFAULT_STATUS);
        return TypeKit.getInt(memberProduct, "cnt");
    }
}